#include "Basic.h"
#ifdef _MSC_VER
#include <Windows.h>
#else
#include <time.h>
#include <memory.h>
#endif

namespace zl
{
	Object::~Object()
	{
	}

	NotCopyable::NotCopyable()
	{
	}

	NotCopyable::NotCopyable(const NotCopyable&)
	{
	}

	NotCopyable& NotCopyable::operator=(const NotCopyable&)
	{
		return *this;
	}



	Interface::~Interface()
	{

	}

#ifdef _MSC_VER
	DateTime SystemTimeToDateTime(const SYSTEMTIME& systemTime)
	{
		DateTime dateTime;
		dateTime.year = systemTime.wYear;
		dateTime.month = systemTime.wMonth;
		dateTime.dayOfWeek = systemTime.wDayOfWeek;
		dateTime.day = systemTime.wDay;
		dateTime.hour = systemTime.wHour;
		dateTime.minute = systemTime.wMinute;
		dateTime.second = systemTime.wSecond;
		dateTime.milliseconds = systemTime.wMilliseconds;

		FILETIME fileTime;
		SystemTimeToFileTime(&systemTime, &fileTime);
		ULARGE_INTEGER largeInteger;
		largeInteger.HighPart = fileTime.dwHighDateTime;
		largeInteger.LowPart = fileTime.dwLowDateTime;
		dateTime.filetime = largeInteger.QuadPart;
		dateTime.totalMilliseconds = dateTime.filetime / 10000;

		return dateTime;
	}

	SYSTEMTIME DateTimeToSystemTime(const DateTime& dateTime)
	{
		ULARGE_INTEGER largeInteger;
		largeInteger.QuadPart = dateTime.filetime;
		FILETIME fileTime;
		fileTime.dwHighDateTime = largeInteger.HighPart;
		fileTime.dwLowDateTime = largeInteger.LowPart;

		SYSTEMTIME systemTime;
		FileTimeToSystemTime(&fileTime, &systemTime);
		return systemTime;
	}
#else
	DateTime ConvertTMToDateTime(tm* timeinfo)
	{
		time_t timer = mktime(timeinfo);
		DateTime dt;
		dt.year = timeinfo->tm_year + 1900;
		dt.month = timeinfo->tm_mon + 1;
		dt.day = timeinfo->tm_mday;
		dt.dayOfWeek = timeinfo->tm_wday;
		dt.hour = timeinfo->tm_hour;
		dt.minute = timeinfo->tm_min;
		dt.second = timeinfo->tm_sec;
		dt.milliseconds = 0;
		dt.filetime = (zuint64_t)timer;
		dt.totalMilliseconds = (zuint64_t)(timer * 1000);
		return dt;
	}
#endif

	DateTime DateTime::LocalTime()
	{
#ifdef _MSC_VER
		SYSTEMTIME systemTime;
		GetLocalTime(&systemTime);
		return SystemTimeToDateTime(systemTime);
#else
		time_t timer = time(nullptr);
		tm* timeinfo = localtime(&timer);
		return ConvertTMToDateTime(timeinfo);
#endif
	}

	DateTime DateTime::UtcTime()
	{
#ifdef _MSC_VER
		SYSTEMTIME utcTime;
		GetSystemTime(&utcTime);
		return SystemTimeToDateTime(utcTime);
#else
		time_t timer = time(nullptr);
		tm* timeinfo = gmtime(&timer);
		return ConvertTMToDateTime(timeinfo);
#endif
	}

	DateTime DateTime::FromDateTime(zint _year, zint _month, zint _day, zint _hour, zint _minute, zint _second, zint _milliseconds)
	{
#ifdef _MSC_VER
		SYSTEMTIME systemTime;
		memset(&systemTime, 0, sizeof(systemTime));
		systemTime.wYear = (WORD)_year;
		systemTime.wMonth = (WORD)_month;
		systemTime.wDay = (WORD)_day;
		systemTime.wHour = (WORD)_hour;
		systemTime.wMinute = (WORD)_minute;
		systemTime.wSecond = (WORD)_second;
		systemTime.wMilliseconds = (WORD)_milliseconds;

		FILETIME fileTime;
		SystemTimeToFileTime(&systemTime, &fileTime);
		FileTimeToSystemTime(&fileTime, &systemTime);
		return SystemTimeToDateTime(systemTime);
#else
		tm timeinfo;
		memset(&timeinfo, 0, sizeof(timeinfo));
		timeinfo.tm_year = _year - 1900;
		timeinfo.tm_mon = _month - 1;
		timeinfo.tm_mday = _day;
		timeinfo.tm_hour = _hour;
		timeinfo.tm_min = _minute;
		timeinfo.tm_sec = _second;
		return ConvertTMToDateTime(&timeinfo);
#endif
	}

	DateTime DateTime::FromFileTime(zuint64_t filetime)
	{
#ifdef _MSC_VER
		ULARGE_INTEGER largeInteger;
		largeInteger.QuadPart = filetime;
		FILETIME fileTime;
		fileTime.dwHighDateTime = largeInteger.HighPart;
		fileTime.dwLowDateTime = largeInteger.LowPart;

		SYSTEMTIME systemTime;
		FileTimeToSystemTime(&fileTime, &systemTime);
		return SystemTimeToDateTime(systemTime);
#else
		time_t timer = (time_t)filetime;
		tm* timeinfo = localtime(&timer);
		return ConvertTMToDateTime(timeinfo);
#endif
	}

	DateTime::DateTime()
		:year(0)
		, month(0)
		, day(0)
		, hour(0)
		, minute(0)
		, second(0)
		, milliseconds(0)
		, filetime(0)
	{
	}

	DateTime DateTime::ToLocalTime()
	{
#ifdef _MSC_VER
		SYSTEMTIME utcTime = DateTimeToSystemTime(*this);
		SYSTEMTIME localTime;
		SystemTimeToTzSpecificLocalTime(NULL, &utcTime, &localTime);
		return SystemTimeToDateTime(localTime);
#else
		time_t localTimer = time(nullptr);
		time_t utcTimer = mktime(gmtime(&localTimer));
		time_t timer = (time_t)filetime + localTimer - utcTimer;
		tm* timeinfo = localtime(&timer);
		return ConvertTMToDateTime(timeinfo);
#endif
	}

	DateTime DateTime::ToUtcTime()
	{
#ifdef _MSC_VER
		SYSTEMTIME localTime = DateTimeToSystemTime(*this);
		SYSTEMTIME utcTime;
		TzSpecificLocalTimeToSystemTime(NULL, &localTime, &utcTime);
		return SystemTimeToDateTime(utcTime);
#else
		time_t timer = (time_t)filetime;
		tm* timeinfo = gmtime(&timer);
		return ConvertTMToDateTime(timeinfo);
#endif
	}

	DateTime DateTime::Forward(zuint64_t milliseconds)
	{
		return FromFileTime(filetime + milliseconds / 1000);
	}

	DateTime DateTime::Backward(zuint64_t milliseconds)
	{
		return FromFileTime(filetime - milliseconds / 1000);
	}


};